package simulation;

/**
 * @author leon
 * 
 */
public class Sun {
  private static int MINUTES_OF_YEAR = 60 * 24 * 365;
  private static int MINUTES_OF_DAY = 60 * 24;
  private static int SUN_RADIUS = 695500;
  
  private static int MAJOR_AXIS_LENGTH = 152500000;
  // I in formula.
  private static double SUN_SURFACE_INTENSITY = 1e21 / (4 * Math.PI * Math.pow (SUN_RADIUS, 2));

  private static double ORBIT_DEGREE_MINUTE = 360.0 / 365.0 / 24.0 / 60.0;
  private static double SPIN_DEGREE_MINUTE = 360.0 / 24.0 / 60.0;
  private static int MINUTE_VERNAL_EQUINOX = 115200;
  
  private double longitude;
  private int minuteOfYear = MINUTE_VERNAL_EQUINOX;
  private int minuteOfDay = 0;

  private double minorAxisLength;
  private double eccentricity;
  private double tiltOfEarth;
  private double equinoxAngle;
  
  //private double orbitX;
  //private double orbitY;
  /**
   * @param lattitude
   * @param longitude
   */
  public Sun(double longitude, double eccentricity, double tiltOfEarth) {
	double orbitY;
	double orbitX;
    this.longitude = longitude;
    this.eccentricity = eccentricity;
    this.minorAxisLength = Math.sqrt (Math.pow (MAJOR_AXIS_LENGTH, 4) * Math.pow(eccentricity, 2) - Math.pow(MAJOR_AXIS_LENGTH, 2));
    this.tiltOfEarth = tiltOfEarth;
    orbitX = MAJOR_AXIS_LENGTH * Math.cos ((MINUTE_VERNAL_EQUINOX) * ORBIT_DEGREE_MINUTE);
    orbitY = minorAxisLength * Math.cos ((MINUTE_VERNAL_EQUINOX) * ORBIT_DEGREE_MINUTE);
    equinoxAngle = Math.atan (orbitY / orbitX);
  }

  /**
   * @return
   */
  public double getLongitude() {
    return longitude;
  }

  /**
   * @param degree
   */
  public void moveSun(double degree) {
    double tempLon = longitude + degree;

    if (tempLon > 180) {
      longitude = (-180 + (tempLon % 180));
    }
    else {
      longitude = tempLon;
    }
    minuteOfYear = (minuteOfYear + 1) % MINUTES_OF_YEAR;
    minuteOfDay = (minuteOfDay + 1) % MINUTES_OF_DAY;
  }
  
  public void reset() {
    longitude = 0;
  }

  /**
   * @param tL
   * @param bL
   * @param lL
   * @param rL
   * @return
   */
  // FIXME: New project 3 requirements - Orbit - demands function of distance
  // New project 3 requirements - Tilt - demands latRadiation to change
  public float cRadiationFactor(float tL, float bL, float lL, float rL) {
	  float result;
	  //System.out.println ("cRadiationFactor");
    // Average the lattitudes and longitudes to get a middle reading to
    // compute for
    float aveLat = (tL + bL) / 2;
    float aveLon = (lL + rL) / 2;

    // New project 3 requirements - tilt - demands latRadiation to change
    // double latRadiation = Math.cos(Math.toRadians(aveLat));
    //double latRadiation = Math.cos (Math.toRadians(aveLat + 23.0 * Math.cos (.25 * minuteOfDay + ORBIT_DEGREE_MINUTE * minuteOfYear + aveLon)));
    double orbitX = MAJOR_AXIS_LENGTH * Math.cos (Math.toRadians((minuteOfYear - MINUTE_VERNAL_EQUINOX) * ORBIT_DEGREE_MINUTE));
    double orbitY = minorAxisLength * Math.cos (Math.toRadians((minuteOfYear - MINUTE_VERNAL_EQUINOX) * ORBIT_DEGREE_MINUTE));
    double latRadiation = Math.abs (aveLat + tiltOfEarth * Math.cos (Math.toRadians(SPIN_DEGREE_MINUTE * minuteOfDay + Math.atan (orbitY / orbitX) - equinoxAngle + aveLon)));
    // Longitude radiation changes based on the lonitude movement of the sun
    double lonRadiation = Math.cos(Math.toRadians(aveLon - this.longitude));
    
    double distance = Math.sqrt (orbitX * orbitX + orbitY * orbitY);

    // FIXME : Need to propperly account for cooling. If the sun is not
    // shining on a Node then the sun's temperature is 0
    if (lonRadiation < 0) {
      return 0;// (float)((-1 * (latRadiation +(-1*lonRadiation))) /
      // 2);
    }
    else {
    	//result variable is so can view result while debugging
      result = (float) (latRadiation * lonRadiation * SUN_SURFACE_INTENSITY / Math.pow(distance / SUN_RADIUS,2) * Math.pow (10,12));
      return result;//return (float) result;
    }
  }

}
